package com.nenglai.admin.modular.report.service.output;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.nenglai.admin.handler.RequestHolder;
import com.nenglai.admin.modular.report.enums.DocumentEnum;
import com.nenglai.admin.util.COSClientUtil;
import com.nenglai.common.util.FileUtil;
import com.nenglai.model.report.entity.Download;
import com.nenglai.model.report.entity.Template;
import com.nenglai.model.report.service.IDownloadService;
import com.nenglai.model.system.entity.Admin;
import com.nenglai.report.Params;
import com.nenglai.report.enums.ReportEnum;
import com.nenglai.report.util.WordDocxUtil;
import com.qcloud.cos.model.ObjectMetadata;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author kongdehui
 * @date 2021/06/26 10:38
 **/
@Component("cosWordOutput")
public class COSWordOutput implements Output {

    @Resource
    IDownloadService downloadService;

    @Resource
    COSClientUtil cosClientUtil;

    /**
     * 上传地址
     */
    private final String downloadPath = "download";

    @Transactional
    @Override
    public Object output(Template template, File templateFile, Params params) throws Exception {
        FileInputStream in = new FileInputStream(templateFile);
        String suffix = FileUtil.suffix(template.getFilePath());
        // templateFile.delete();  // 获取文件流后，将下载的文件删除
        if (DocumentEnum.DOCUMENT_TYPE_DOCX.getCode().equals(suffix)) {
            return docx(in, template, params, suffix);
        }

        if (DocumentEnum.DOCUMENT_TYPE_DOC.getCode().equals(suffix)) {
            return doc(in, template, params, suffix);
        }
        return null;
    }

    @Override
    public File download(Download download) {
        File file = new File("/tmp/" + download.getId());
        cosClientUtil.getObjectFile(download.getDownload(), file);
        return file;
    }

    private Object doc(FileInputStream in, Template template, Params params, String suffix)
            throws IOException {
        HWPFDocument document = new HWPFDocument(in);
        Range range = document.getRange();
        for (Map.Entry<String, String> entry : params.getParagraphs().entrySet()) {
            String key = DocumentEnum.DOCUMENT_PARSING_BEGIN.getCode() + entry.getKey() + DocumentEnum.DOCUMENT_PARSING_END.getCode();
            range.replaceText(key, entry.getValue());
        }

        Admin user = (Admin) RequestHolder.getRequest().getAttribute("user");
        Download download = new Download();
        download.setUid(user.getId());

        // 导出到下载列表
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        String path = downloadPath + "/" + sdf.format(new Date());
        String filename = path + "/" + IdWorker.get32UUID() + "." + suffix;
        outputDownload(in, document, filename);
        download.setId(IdWorker.get32UUID());
        download.setName(template.getName());
        download.setShared(Integer.parseInt(ReportEnum.REPORT_NOT_SHARED.getValue()));
        download.setDownload(filename);
        download.setCreateTime(new Date());
        download.setUpdateTime(new Date());
        download.setService(params.getService());
        downloadService.save(download);
        HashMap<String, Object> hash = new HashMap<>();
        hash.put("key", download.getId());
        return hash;
    }

    private Object docx(FileInputStream in, Template template, Params params, String suffix)
            throws IOException {
        XWPFDocument doc = new XWPFDocument(in);
        // 替换段落中的指定文字
        WordDocxUtil.replaceInAllParagraphs(doc.getParagraphsIterator(), params.getParagraphs());
        // 替换表格中的指定文字
        WordDocxUtil.replaceInAllTables(doc.getTablesIterator(), params.getParagraphs());

        // 替换表格标记
        /*List<XWPFTable> tables = doc.getTables();
        WordDocxUtil.replaceInTables(tables, params.getTables());*/

        Admin user = (Admin) RequestHolder.getRequest().getAttribute("user");
        Download download = new Download();
        download.setUid(user.getId());

        // 导出到下载列表
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        String path = downloadPath + "/" + sdf.format(new Date());
        String filename = path + "/" + IdWorker.get32UUID() + "." + suffix;
        outputDownload(in, doc, filename);
        download.setId(IdWorker.get32UUID());
        download.setName(template.getName());
        download.setShared(Integer.parseInt(ReportEnum.REPORT_NOT_SHARED.getValue()));
        download.setDownload(filename);
        download.setCreateTime(new Date());
        download.setUpdateTime(new Date());
        download.setService(params.getService());
        downloadService.save(download);
        HashMap<String, Object> hash = new HashMap<>();
        hash.put("key", download.getId());
        return hash;
    }

    /**
     * 存储到目录
     *
     * @param in
     * @param doc
     * @param fileName
     * @return void
     * @author kongdehui
     * @date 2021/06/26 09:40
     */
    private void outputDownload(FileInputStream in,
                                XWPFDocument doc,
                                String fileName
    ) throws IOException {

        File file = new File("/tmp/" + IdWorker.get32UUID());
        FileOutputStream outStream = null;
        FileInputStream inputStream = null;
        try {
            outStream = new FileOutputStream(file);
            doc.write(outStream);
            inputStream = new FileInputStream(file);
            ObjectMetadata objectMetadata = new ObjectMetadata();
            cosClientUtil.putObject(fileName, inputStream, objectMetadata);
            file.delete();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outStream != null) {
                outStream.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
            in.close();
        }

    }

    private void outputDownload(FileInputStream in,
                                HWPFDocument doc,
                                String fileName
    ) throws IOException {

        File file = new File("/tmp/" + IdWorker.get32UUID());
        FileOutputStream outStream = null;
        FileInputStream inputStream = null;
        try {
            outStream = new FileOutputStream(file);
            doc.write(outStream);
            inputStream = new FileInputStream(file);
            ObjectMetadata objectMetadata = new ObjectMetadata();
            cosClientUtil.putObject(fileName, inputStream, objectMetadata);
            file.delete();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outStream != null) {
                outStream.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
            in.close();
        }
    }

}
